package com.xingceng.stock.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.xiceng.stock.entity.StockRtInfo;
import com.xiceng.stock.vo.Stock4EvrDayVO;
import com.xiceng.stock.vo.Stock4MinuteVO;
import com.xiceng.stock.vo.StockUpdownVO;

import com.xingceng.stock.config.StockInfoConfig;
import com.xingceng.stock.enums.CodeEnum;
import com.xingceng.stock.exception.StockException;
import com.xingceng.stock.response.PageResult;
import com.xingceng.stock.service.StockRtInfoService;
import com.xingceng.stock.mapper.StockRtInfoMapper;
import com.xingceng.stock.util.DateTimeUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author ZYZ
* @description 针对表【stock_rt_info(个股详情信息表)】的数据库操作Service实现
* @createDate 2025-11-07 14:39:26
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class StockRtInfoServiceImpl extends ServiceImpl<StockRtInfoMapper, StockRtInfo>
    implements StockRtInfoService{

    private final StockRtInfoMapper stockRtInfoMapper;

    private final StockInfoConfig stockInfoConfig;

    @Override
    public List<StockUpdownVO> stockIncreaseLimit() {
        //1.直接调用mapper查询前10的数据 TODO 以时间顺序取前10
        //优化：
        //获取当前最近有效时间
        Date curDateTime = null;
        //mock数据
        String mockStr="2021-12-27 09:47:00";
        try {
            curDateTime= DateUtils.parseDate(mockStr, "yyyy-MM-dd HH:mm:ss");
        } catch (ParseException e) {
            throw new StockException( CodeEnum.DATE_PARSE_ERROR);
        }

        List<StockUpdownVO> infos=stockRtInfoMapper.stockIncreaseLimit(curDateTime);
        //2.判断是否有数据
        if (CollectionUtils.isEmpty(infos)) {
           throw new StockException( CodeEnum.NO_RESPONSE_DATA);
        }
        return infos;
    }

    @Override
    public PageResult<StockUpdownVO> stockPage(Integer page, Integer pageSize) {
        //1.设置分页参数
        PageHelper.startPage(page,pageSize);
        //2.通过mapper查询
        List<StockUpdownVO> infos= stockRtInfoMapper.stockAll();
        if (CollectionUtils.isEmpty(infos)) {
           throw new StockException(CodeEnum.NO_RESPONSE_DATA);
        }
        //3.封装到PageResult下
        //3.1 封装PageInfo对象
        PageInfo<StockUpdownVO> listPageInfo = new PageInfo<StockUpdownVO>(infos);
        //3.2 将PageInfo转PageResult
        PageResult<StockUpdownVO> pageResult = new PageResult<>(listPageInfo);
        //4.封装R响应对象
        return pageResult;
    }

    @Override
    public Map upDownCount() {
        //1.获取股票最近的有效交易日期,精确到秒
        LocalDateTime curDateTime = LocalDateTime.now();

        //当前最近有效期
        Date curTime = Date.from(curDateTime.atZone(java.time.ZoneId.systemDefault()).toInstant());        //开盘日期
        LocalDate oldOpenTime = DateTimeUtil.getOpenDate(curDateTime).toLocalDate();
        Date openTime = Date.from(oldOpenTime.atStartOfDay(java.time.ZoneId.systemDefault()).toInstant());
        //TODO mock_data 后续数据实时获取时，注释掉
        String curTimeStr="20220106142500";
        //对应开盘日期 mock_data
        String openTimeStr="20220106092500";
        //把openTimeStr转成Date形式赋值给openTime
        try {
            openTime =  DateUtils.parseDate(openTimeStr, "yyyyMMddHHmmss");
            curTime = DateUtils.parseDate(curTimeStr, "yyyyMMddHHmmss");
        } catch (ParseException e) {
            throw new StockException(CodeEnum.DATE_PARSE_ERROR);
        }
        //2.统计涨停的数据 约定：1代表涨停 0：跌停
        List<Map> upCount = stockRtInfoMapper.upDownCount(curTime, openTime, 1);
        //3.统计跌停的数据
        List<Map> downCount = stockRtInfoMapper.upDownCount(curTime, openTime, 0);
        //4.组装数据到map
        HashMap<String, List<Map>> info = new HashMap<>();
        info.put("upList",upCount);
        info.put("downList",downCount);
        //5.响应
        return info;
    }

    @Override
    public void stockExport(HttpServletResponse response, Integer page, Integer pageSize) {
        try {
            //1.设置响应数据的类型:excel
            response.setContentType("application/vnd.ms-excel");
            //2.设置响应数据的编码格式
            response.setCharacterEncoding("utf-8");
            //3.设置默认的文件名称
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("stockRt", StandardCharsets.UTF_8);
            //设置默认文件名称
            response.setHeader("content-disposition", "attachment;filename=" + fileName + ".xlsx");
            //4.分页查询股票数据
            PageHelper.startPage(page,pageSize);
            List<StockUpdownVO> infos = this.stockRtInfoMapper.stockAll();
            Gson gson = new Gson();
            List<StockUpdownVO> excelDomains = infos.stream().map(info -> {
                StockUpdownVO domain=new StockUpdownVO();
                BeanUtils.copyProperties(info,domain);
                return domain;
            }).collect(Collectors.toList());
            //5.导出
            EasyExcel.write(response.getOutputStream(),StockUpdownVO.class).sheet("股票数据").doWrite(excelDomains);
        } catch (IOException e) {
            log.info("股票excel数据导出异常，当前页：{}，每页大小：{}，异常信息：{}",page,pageSize,e.getMessage());
            throw new StockException(CodeEnum.EXPORT_ERROR);
        }
    }

    @Override
    public Map stockUpDownScopeCount() {
        try {
            //1.获取当前时间下最近的一个股票交易时间 精确到秒
            LocalDateTime avlDateTime = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
            Date avlDate = Date.from(avlDateTime.atZone(java.time.ZoneId.systemDefault()).toInstant());
            //TODO 后续删除 mock-data
            String  mockDate="20220106095500";
            avlDate =DateUtils.parseDate(mockDate, "yyyyMMddHHmmss");
            //2.查询
            List<Map> maps=stockRtInfoMapper.stockUpDownScopeCount(avlDate);
            //获取去股票涨幅区间的集合
            List<String> upDownRange = stockInfoConfig.getUpDownRange();
            //将list集合下的字符串映射成Map对象
            List<Map> orderMap = upDownRange.stream().map(key -> {
                Optional<Map> title = maps.stream().filter(map -> key.equals(map.get("title"))).findFirst();
                //判断对应的map是否存在
                Map tmp = null;
                if (title.isPresent()) {
                    tmp = title.get();
                } else {
                    tmp = new HashMap();
                    tmp.put("title", key);
                    tmp.put("count", 0);
                }
                return tmp;
            }).collect(Collectors.toList());


            //3.组装data
            HashMap<String, Object> data = new HashMap<>();
            data.put("time",avlDateTime.toString());
            data.put("infos",orderMap);
            //返回响应数据
            return data;
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<Stock4MinuteVO> stockScreenTimeSharing(String code) {
        //1.获取最近有效的股票交易时间
        LocalDateTime curDateTime = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        //获取当前日期
        Date curDate = Date.from(curDateTime.atZone(java.time.ZoneId.systemDefault()).toInstant());
        //获取当前日期对应的开盘日期
        LocalDateTime openOldDate = DateTimeUtil.getOpenDate(curDateTime);
        Date openDate = Date.from(openOldDate.atZone(java.time.ZoneId.systemDefault()).toInstant());
        //TODO 后续删除 mock-data
        String mockDate="20220106142500";
        try {
            curDate= DateUtils.parseDate(mockDate, "yyyyMMddHHmmss");
            String openDateStr="20220106093000";
            openDate= DateUtils.parseDate(openDateStr, "yyyyMMddHHmmss");
        } catch (ParseException e) {
            throw new StockException(CodeEnum.DATE_PARSE_ERROR);
        }
        List<Stock4MinuteVO> maps= stockRtInfoMapper.stockScreenTimeSharing(code,openDate,curDate);
        //响应前端
        return maps;
    }

    @Override
    public List< Stock4EvrDayVO> stockCreenDkLine(String stockCode) {
        //获取当前日期前推20天
        LocalDateTime curDateTime = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        //当前时间节点
        Date curTime = new Date();
        //前推20
        LocalDateTime pre20DayOld = curDateTime.minusDays(20);
        Date pre20Day = Date.from(pre20DayOld.atZone(java.time.ZoneId.systemDefault()).toInstant());

        //TODO 后续删除
        try {
            String avlDate="20220106142500";
            curTime= DateUtils.parseDate(avlDate, "yyyyMMddHHmmss");
            String openDate="20220101093000";
            pre20Day= DateUtils.parseDate(openDate, "yyyyMMddHHmmss");
        } catch (ParseException e) {
            throw new StockException(CodeEnum.DATE_PARSE_ERROR);
        }
        List<Stock4EvrDayVO> infos = stockRtInfoMapper.stockCreenDkLine(stockCode, pre20Day, curTime);
        return infos;
    }
}




